/*
 * @Author: 来自火星的码农 15122322+heyzhi@user.noreply.gitee.com
 * @Date: 2025-10-02 18:17:41
 * @LastEditors: 来自火星的码农 15122322+heyzhi@user.noreply.gitee.com
 * @LastEditTime: 2025-10-03 17:17:55
 * @FilePath: /GateServer/src/util/config.h
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE   
 */


 #pragma  once
#include <algorithm>
#include <cctype>
#include <exception>
#include <memory>
#include <mutex>
#include <string>
#include "boost/lexical_cast.hpp"
#include "logger.h"
#include "yaml-cpp/yaml.h"
namespace Yizhi {
    //配置基类
    class ConfigVarBase{
        public:
        typedef std::shared_ptr<ConfigVarBase> ptr ;
        ConfigVarBase(std::string name,std::string desrciption)
        :m_name(name)
        ,m_description(desrciption){
            std::transform(m_name.begin(),m_name.end(),m_name.begin(),::tolower);
        }
        virtual ~ConfigVarBase(){}

        //将value转换成string
        virtual void Tostring()=0;
        //从string提取value
        virtual bool Fromstring(const std::string& )=0; 
        std::string getname(){return  m_name;}
        std::string getdesription(){return m_description;}

        private:
        std::string m_name;
        std::string m_description;
    };


    template <class F,class T>
    class Lexical_cast{
        public:
        Lexical_cast()=default;
        public: 
            T operator()(const F &v){
            return boost::lexical_cast<T>(v);
        }
    };

    //模版类用于配置基础类型
  template<class T,class Fromstr=Lexical_cast<std::string,T>,class Tostr=Lexical_cast<T,std::string>>
    class ConfigVar:public ConfigVarBase{
        public:
        using MutexType=std::mutex;
        using Lock = std::lock_guard<MutexType>;

        typedef  std::shared_ptr<ConfigVar> ptr ;



        
        ConfigVar(std::string name,T v,std::string desrciption)
        :ConfigVarBase(name,desrciption)
        ,m_value(v){
            
        }

        void Tostring()override{
            try {
                Lock lock(m_mutex);
                Tostr()(m_value);
            } catch (std::exception&e) {
                LOG_ERROR("convert value to string error");
            }
        }
        bool Fromstring(const std::string &str)override{
            try {
                setvalue(Fromstr()(str));
                return true;
            } catch (std::exception& e) {
               
            }
            return false;
        }
        T getvalue(){
            Lock lock(m_mutex);
            return m_value;
        }
        void setvalue(T v){
            Lock lock(m_mutex);
            if(v==m_value){
                return;
            }
            m_value=v;
        }


        private:
        T m_value;
        MutexType m_mutex;
    };




    class ConfigMgr{

        public:
        using MutexTpye=std::mutex;
        using Lock =std::lock_guard<MutexTpye>;
        typedef std::map<std::string,Yizhi::ConfigVarBase::ptr> ConfigvarMap ;
        
        template<class T>
        static typename  ConfigVar<T>::ptr Lookup(const std::string &name,const T&default_value,std::string desricption=""){
            Lock lock(GetMutex());
            auto it=Getdatas().find(name);
            if(it!=Getdatas().end()){
                auto res=std::dynamic_pointer_cast<ConfigVar<T>>(it->second);
                if(res){
                    LOG_INFO("lookup name"+name+"exit");
                    return res;
                }
                else{
                    LOG_ERROR("Lookup name exit but type not");
                    return nullptr;
                }
            }

            if(name.find_first_not_of("abcdefghigklmnopqrstuvwxyz_.0123456789")!=std::string::npos){
                    LOG_ERROR("name invaild");
            }

            typename ConfigVar<T>::ptr v(new  ConfigVar<T>(name,default_value,desricption));
            Getdatas()[name]=v;
            return v;
            

           
        }   
        template<class T>
        static typename ConfigVar<T>::ptr Lookup(const std::string &name){
            auto it=Getdatas().find(name);
            if(it==Getdatas().end()){
                return nullptr;
            }
            auto res=std::dynamic_pointer_cast<ConfigVar<T>>(it->second);
        }


        static void LoadFromYaml(YAML::Node &node);

        static ConfigVarBase::ptr LookupBase(const std::string &name);

        private:
        static ConfigvarMap& Getdatas(){
            static ConfigvarMap s_datas;
            return s_datas;
        }

        static MutexTpye& GetMutex(){
            static MutexTpye m_mutex;
            return m_mutex;
        }

      
    };
}